package com.cloudkinto.common.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.XMLOutputter;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

/**
 * Created by alany on 2018/7/10.
 */
public class XmlUtils {
    public static JSONObject xml2Json(String xmlStr) throws JDOMException, IOException {
        if (StringUtils.isEmpty(xmlStr)) {
            return null;
        }
        xmlStr = xmlStr.replaceAll("\\\n", "");
        byte[] xml = xmlStr.getBytes(StandardCharsets.UTF_8);
        JSONObject json = new JSONObject();
        InputStream is = new ByteArrayInputStream(xml);
        SAXBuilder sb = new SAXBuilder();
        Document doc = sb.build(is);
        Element root = doc.getRootElement();
        json.put(root.getName(), iterateElement(root));

        return json;
    }

    private static JSONObject iterateElement(Element element) {
        List<Element> node = element.getChildren();
        JSONObject obj = new JSONObject();
        List list = null;
        for (Element child : node) {
            list = new LinkedList();
            String text = child.getTextTrim();
            if (StringUtils.isBlank(text)) {
                if (child.getChildren().size() == 0) {
                    continue;
                }
                if (obj.containsKey(child.getName())) {
                    list = (List) obj.get(child.getName());
                }
                list.add(iterateElement(child)); //遍历child的子节点
                obj.put(child.getName(), list);
            } else {
                if (obj.containsKey(child.getName())) {
                    Object value = obj.get(child.getName());
                    try {
                        list = (List) value;
                    } catch (ClassCastException e) {
                        list.add(value);
                    }
                }
                if (child.getChildren().size() == 0) { //child无子节点时直接设置text
                    obj.put(child.getName(), text);
                } else {
                    list.add(text);
                    obj.put(child.getName(), list);
                }
            }
        }
        return obj;
    }

    /**
     * 37      * JavaBean转换成xml 默认编码UTF-8
     * 38      *
     * 39      * @param obj
     * 40      * @param writer
     * 41      * @return
     * 42
     */
    public static String convertToXml(Object obj, String hedaer, String ender) {
        return convertToXml(obj, "UTF-8", hedaer, ender);
    }

    /**
     * 37      * JavaBean转换成xml 默认编码UTF-8
     * 38      *
     * 39      * @param obj
     * 40      * @param writer
     * 41      * @return
     * 42
     */
    public static String convertToXml(Object obj) {
        return convertToXml(obj, "UTF-8", "", "");
    }

    /**
     * JavaBean转换成xml
     *
     * @param obj
     * @param encoding
     * @return
     */
    public static String convertToXml(Object obj, String encoding, String header, String ender) {
        String result = null;
        try {
            JAXBContext context = null;
            if (obj instanceof List) {
                context = JAXBContext.newInstance(((List) obj).get(0).getClass());
            } else {
                context = JAXBContext.newInstance(obj.getClass());
            }
            Marshaller marshaller = context.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);
            //去掉生成xml的默认报文头
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
            StringWriter writer = new StringWriter();
            writer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "\n    ");
            if (!StringUtils.isEmpty(header)) {
                writer.append(header + "\n");
            }
            if (obj instanceof List) {
                for (Object o :
                        ((List) obj)) {
                    marshaller.marshal(o, writer);
                    writer.append("\n");
                }
            } else {
                marshaller.marshal(obj, writer);
            }
            if (!StringUtils.isEmpty(ender)) {
                writer.append("\n" + ender);
                result = writer.toString();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     *功能描述 json转xml
     *@author zhujiale
     *@date
     */
    public static  String JsonToXml(Object json) {
        if (json == null) {
            return null;
        } else {
            Element elements = new Element("xml");
            getXMLFromObject(json, "xml", elements);
            XMLOutputter xmlOut = new XMLOutputter();
            String res = xmlOut.outputString(elements);
            return res;
        }
    }

    private static void getXMLFromObject(Object obj,String tag,Element parent)
    {
        if(obj==null)
            return;
        Element child;
        String eleStr;
        Object childValue;
        if(obj instanceof JSONObject)
        {
            JSONObject jsonObject=(JSONObject)obj;
            for(Object temp:jsonObject.keySet())
            {
                eleStr=temp.toString();
                childValue=jsonObject.get(temp);
                child=new Element(eleStr);
                if(childValue instanceof JSONArray)
                    getXMLFromObject(childValue,eleStr,parent);
                else{
                    parent.addContent(child);
                    getXMLFromObject(childValue,eleStr,child);
                }
            }
        }else if(obj instanceof JSONArray){
            JSONArray jsonArray=(JSONArray)obj;
            for(int i=0;i<jsonArray.size();i++)
            {
                childValue=jsonArray.get(i);
                child=new Element(tag);
                parent.addContent(child);
                getXMLFromObject(childValue,tag,child);
            }
        }else if(obj instanceof Date){
            SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            parent.setText(sf.format((Date)obj));
        }else{
            parent.setText(obj.toString());
        }
    }

}